﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace RPGProject.IOBuffers
{
    /// <summary>
    /// A subclass of OutputBuffer that allows standard console output.
    /// </summary>
    class LogOutputBuffer : OutputBuffer
    {
        /// <summary>
        /// The queue of text in the log.
        /// </summary>
        private Queue<String> toPrint;
        private bool lineSymbol;
        public LogOutputBuffer(int x, int y, bool lineSymbol = false, bool addWriter = true)
            : base(x, y, new CharInfo(' '), addWriter)
        {
            this.lineSymbol = lineSymbol;
            toPrint = new Queue<string>();
        }
        /// <summary>
        /// Writes the string to the buffer, splitting it between lines.
        /// </summary>
        /// <param name="s">The string to be written.</param>
        public void WriteLine(String s)
        {
            s = ((this.lineSymbol) ? "> " : "") + s;
            // enqueue multiple lines into the print queue
            // splits the string into multiple lines to fit queue
            do
            {
                this.toPrint.Enqueue(s.Substring(0, Math.Min(this.width, s.Length)));
                s = s.Substring(Math.Min(this.width, s.Length), s.Length - Math.Min(this.width, s.Length));
            } while (s.Length != 0);
            // dequeues the items that over the limit
            while (this.toPrint.Count > this.height)
            {
                this.toPrint.Dequeue();
            }
            this.WriteToBuffer();
        }
        /// <summary>
        /// A private helper method that renders the characters onto the log.
        /// </summary>
        private void WriteToBuffer()
        {
            String[] temp = this.toPrint.ToArray();
            for (int i = 0; i < temp.Length; i++)
            {
                for (int j = 0; j < temp[i].Length; j++)
                {
                    this[j, i] = new CharInfo(temp[i][j]);
                }
                for (int j = 0; j < this.width - temp[i].Length; j++)
                {
                    this[j + temp[i].Length, i] = new CharInfo(' ');
                }
            }
        }
        /// <summary>
        /// An override of RenderTo that fixes some rendering issues specifically with LogOutputBuffer.  Otherwise, renders the buffer to a specific (x, y) in Cartesian coordinates.
        /// </summary>
        /// <param name="startX"></param>
        /// <param name="startY"></param>
        /// <param name="solo"></param>
        /// <param name="forceRender"></param>
        public override void RenderTo(int startX, int startY, bool solo, bool forceRender)
        {
            if (this.toPrint.Count + 1 != this.height)
                base.RenderTo(startX, startY, solo, forceRender);
            else if (this.toPrint.Count + 1 == this.height)
                base.RenderTo(startX, startY, solo, true);
        }
        public static LogOutputBuffer CreateLogFromFile(String filename, int width, int height)
        {
            LogOutputBuffer ret = new LogOutputBuffer(width, height, false, true);
            StreamReader sr = new StreamReader(filename);
            // begin file loop
            while (!sr.EndOfStream)
            {
                ret.WriteLine(sr.ReadLine());
            }
            return ret;
        }
    }
}
